import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class AppRouterDelegate extends RouterDelegate<String>
    with PopNavigatorRouterDelegateMixin, ChangeNotifier {
  String _routePath = '/';
  final RouteFactory onGeneratedRoute;

  AppRouterDelegate({required this.onGeneratedRoute});

  @override
  Widget build(BuildContext context) {
    List<String> routeNames = [];
    if (_routePath == '/') {
      routeNames.add('/');
    } else {
      routeNames = _routePath.split('/').map((e) => '/$e').toList();
    }
    return Navigator(
      key: navigatorKey,
      pages: routeNames
          .map(
            (name) => _Page(
              name: name,
              routeFactory: onGeneratedRoute,
            ),
          )
          .toList(),
      onPopPage: (route, result) {
        if (route.settings.name == '/') {
          return false;
        }
        return route.didPop(result);
      },
    );
  }

  Future<void> push(String routeName) {
    _routePath += _routePath == '/' ? '' : '/' + '$routeName';
    notifyListeners();
    return SynchronousFuture(null);
  }

  @override
  Future<bool> popRoute() {
    if (_routePath == '/') {
      return SynchronousFuture(false);
    }
    _routePath = (_routePath.split('/')..removeLast()).join('/');
    notifyListeners();
    return SynchronousFuture(true);
  }

  @override
  String? get currentConfiguration => _routePath;

  @override
  Future<void> setNewRoutePath(String configuration) {
    assert(
      configuration.startsWith('/'),
      '$AppRouterDelegate setNewRoutePath $configuration is not startwith /',
    );
    notifyListeners();
    _routePath = configuration;
    return SynchronousFuture(null);
  }

  @override
  GlobalKey<NavigatorState>? get navigatorKey => GlobalKey<NavigatorState>();

  static AppRouterDelegate of(BuildContext context) {
    return Router.of(context).routerDelegate as AppRouterDelegate;
  }
}

class _Page extends Page {
  final String name;
  final RouteFactory routeFactory;
  _Page({
    required this.name,
    required this.routeFactory,
  }) : super(key: ValueKey(name), name: name);

  @override
  Route createRoute(BuildContext context) => routeFactory(this)!;
}
